<script setup lang="ts">
import { ref, computed, onMounted, reactive, watch } from 'vue'
// import { navigateToUrl } from 'single-spa'
import { useStore } from 'stores/store'
// import { useRoute, useRouter } from 'vue-router'
import { i18n } from 'boot/i18n'
import api from 'src/api'
import { date, Notify, QTableProps } from 'quasar'

import type { MeetingReservation, ReservationStatus, RoomType } from 'src/api/service'

// import CloudPlatformLogo from 'components/ui/CloudPlatformLogo.vue'

// import useCopyToClipboard from 'src/composables/useCopyToClipboard'
// import useExceptionNotifier from 'src/composables/useExceptionNotifier'

// const props = defineProps({
//   groupId: {
//     type: String,
//     required: false,
//     default: ''
//   },
//   isHideGroup: {
//     type: Boolean,
//     required: false,
//     default: false
//   }
// })
// const emits = defineEmits(['change', 'delete'])

const { tc } = i18n.global
// const store = useStore()
// const route = useRoute()
// const router = useRouter()

// const exceptionNotifier = useExceptionNotifier()
// const clickToCopy = useCopyToClipboard()

// table row hover
const hoverRow = ref('')
const onMouseEnterRow = (rowName: string) => {
  hoverRow.value = rowName
}
const onMouseLeaveRow = () => {
  hoverRow.value = ''
}

// 格式化日期函数 (接受时间戳 number 或 ISO 字符串)
const formatDate = (timestampOrString: number | string | undefined | null): string => {
  if (!timestampOrString) return ''
  let timestampMs: number
  if (typeof timestampOrString === 'number') {
    timestampMs = timestampOrString * 1000
  } else {
    try {
      timestampMs = new Date(timestampOrString).getTime()
    } catch (e) {
      return 'Invalid Date'
    }
  }
  if (isNaN(timestampMs)) return 'Invalid Date'
  return date.formatDate(timestampMs, 'YYYY-MM-DD HH:mm')
}

/* 筛选 */

// 定义初始筛选状态
const getInitialFilter = () => ({
  from: '',
  to: '',
  statusSelection: 'all' as ReservationStatus | 'all',
  roomTypeSelection: 'all' as RoomType | 'all',
  txMeetingCode: ''
})

const filter = reactive({
  from: getInitialFilter().from,
  to: getInitialFilter().to,

  // 预定状态
  statusSelection: getInitialFilter().statusSelection,
  statusOptions: [
    {
      label: tc('全部状态'),
      value: 'all'
    },
    {
      label: tc('已预定'),
      value: 'reserved'
    },
    {
      label: tc('已取消'),
      value: 'cancelled'
    }
  ],

  // 会议室类型
  roomTypeSelection: getInitialFilter().roomTypeSelection,
  roomTypeOptions: [
    {
      label: tc('全部类型'),
      value: 'all'
    },
    {
      label: tc('50方'),
      value: 50
    },
    {
      label: tc('100方'),
      value: 100
    },
    {
      label: tc('300方'),
      value: 300
    },
    {
      label: tc('500方'),
      value: 500
    },
    {
      label: tc('1000方'),
      value: 1000
    }],

  // 腾讯会议号
  txMeetingCode: getInitialFilter().txMeetingCode

})

// 检查当前筛选条件是否与初始状态一致
const isFilterInInitialState = () => {
  const initialFilter = getInitialFilter()
  return filter.from === initialFilter.from &&
    filter.to === initialFilter.to &&
    filter.statusSelection === initialFilter.statusSelection &&
    filter.roomTypeSelection === initialFilter.roomTypeSelection &&
    filter.txMeetingCode === initialFilter.txMeetingCode
}

// 重置所有搜索条件
const resetFilters = () => {
  const initialFilter = getInitialFilter()
  filter.from = initialFilter.from
  filter.to = initialFilter.to
  filter.statusSelection = initialFilter.statusSelection
  filter.roomTypeSelection = initialFilter.roomTypeSelection
  filter.txMeetingCode = initialFilter.txMeetingCode
}

// 监听筛选条件变化
const isFiltersChanged = ref(false)

watch(filter, () => {
  // 根据是否与初始状态一致来设置isFiltersChanged
  isFiltersChanged.value = !isFilterInInitialState()
  // 清空会议数据
  table.rows = []
  resetPagination()
})

/* filter end */

/* table start */
const table = reactive({
  columns: computed<QTableProps['columns']>(() => [
    {
      name: 'creation_time',
      label: (() => tc('预定创建时间'))(),
      field: 'creation_time',
      sortable: true,
      align: 'center',
      classes: 'ellipsis',
      style: 'padding: 15px 0px',
      headerStyle: 'padding: 0 2px',
      sort: (a: number | string, b: number | string) => {
        // 转换为时间戳进行比较
        const timeA = typeof a === 'number' ? a : new Date(a).getTime() / 1000
        const timeB = typeof b === 'number' ? b : new Date(b).getTime() / 1000
        return timeA - timeB
      }
    },
    {
      name: 'subject',
      label: (() => tc('会议主题'))(),
      field: 'subject',
      align: 'center',
      classes: 'ellipsis',
      headerStyle: 'padding: 0 0 0 1px',
      style: 'padding: 15px 0px; min-width: 150px; max-width: 200px; word-break: break-all; word-wrap: break-word; white-space: normal;'
    },
    {
      name: 'tx_meeting_code',
      label: (() => tc('会议号'))(),
      field: 'tx_meeting_code',
      align: 'center' as 'left' | 'right' | 'center',
      classes: 'ellipsis',
      headerStyle: 'padding: 0 0 0 1px',
      style: 'padding: 15px 0px'
    },
    {
      name: 'start_time',
      label: (() => tc('开始时间'))(),
      field: 'start_time',
      sortable: true,
      align: 'center',
      classes: 'ellipsis',
      style: 'padding: 15px 0px; min-width: 150px; max-width: 200px; word-break: break-all; word-wrap: break-word; white-space: normal;',
      headerStyle: 'padding: 0 2px; ',
      sort: (a: number | string, b: number | string) => {
        // 转换为时间戳进行比较
        const timeA = typeof a === 'number' ? a : new Date(a).getTime() / 1000
        const timeB = typeof b === 'number' ? b : new Date(b).getTime() / 1000
        return timeA - timeB
      }
    },
    {
      name: 'end_time',
      label: (() => tc('结束时间'))(),
      field: 'end_time',
      sortable: true,
      align: 'center',
      classes: 'ellipsis',
      style: 'padding: 15px 0px',
      headerStyle: 'padding: 0 2px',
      sort: (a: number | string, b: number | string) => {
        // 转换为时间戳进行比较
        const timeA = typeof a === 'number' ? a : new Date(a).getTime() / 1000
        const timeB = typeof b === 'number' ? b : new Date(b).getTime() / 1000
        return timeA - timeB
      }
    },
    {
      name: 'room_type',
      label: (() => tc('会议室类型'))(),
      field: 'room_type',
      align: 'center',
      classes: 'ellipsis',
      style: 'padding: 15px 0px',
      headerStyle: 'padding: 0 2px'
    },
    {
      name: 'creator',
      label: (() => tc('会议创建人'))(),
      field: 'creator',
      align: 'center',
      classes: 'ellipsis',
      style: 'padding: 15px 0px',
      headerStyle: 'padding: 0 2px'
    },
    {
      name: 'user',
      label: (() => tc('会议预定人'))(),
      field: 'user',
      align: 'center',
      classes: 'ellipsis',
      style: 'padding: 15px 0px',
      headerStyle: 'padding: 0 2px'
    },
    {
      name: 'reserve_status',
      label: (() => tc('预定状态'))(),
      field: 'reserve_status',
      align: 'center',
      classes: 'ellipsis',
      style: 'padding: 15px 0px',
      headerStyle: 'padding: 0 2px'
    },
    {
      name: 'room_status',
      label: (() => tc('会议室状态'))(),
      field: 'room_status',
      align: 'center',
      classes: 'ellipsis',
      style: 'padding: 15px 0px',
      headerStyle: 'padding: 0 2px'
    },
    {
      name: 'operation',
      label: (() => tc('操作'))(),
      field: 'operation',
      align: 'center',
      classes: 'ellipsis',
      style: 'padding: 15px 0px;width: 150px;',
      headerStyle: 'padding: 0 2px'
    }]),
  // visibleColumns: computed(() => [
  //   'id',
  //   ...(props.groupId && !props.isHideGroup ? ['group'] : []),
  //   'service',
  //   'type',
  //   'config',
  //   'time',
  //   'order_type',
  //   'pay_type',
  //   'pay',
  //   'status',
  //   'operation'
  // ]),
  isLoading: false,
  rows: [] as MeetingReservation[] // 当前页面的数据，喂给q-table
})

const passInputCheck = () => {
  // place holder
  return true
}
// 根据当前搜索条件，更新rows，并更新count值
const loadRows = async () => {
  // check input
  if (!passInputCheck()) {
    return
  }

  // filter status
  isFiltersChanged.value = false

  // table loading
  table.isLoading = true
  // request
  try {
    const resp = await api.service.txMeeting.listReservations({
      'as-admin': true,
      page: pagination.page,
      page_size: pagination.rowsPerPage,
      ...(filter.statusSelection !== 'all' && { status: filter.statusSelection }),
      ...(filter.roomTypeSelection !== 'all' && { room_type: filter.roomTypeSelection }),
      ...(filter.statusSelection !== 'all' && { status: filter.statusSelection }),
      ...(filter.txMeetingCode !== '' && { meeting_code: filter.txMeetingCode }),
      start_time_start: filter.from ? Math.floor(new Date(filter.from + ' 00:00:00').getTime() / 1000) : undefined,
      start_time_end: filter.to ? Math.floor(new Date(filter.to + ' 23:59:59').getTime() / 1000) : undefined
    })
    // 拿到rows值，给table用
    table.rows = resp.data.results
    // pagination count
    pagination.count = resp.data.count
  } catch (exception) {
    Notify.create({
      message: tc('获取会议预定失败'),
      type: 'negative',
      icon: 'error',
      position: 'top'
    })

    // 请求无效也可能是用户填写了新的筛选条件，但是请求了旧的页面序数，此时应把页面归为第一页
    resetPagination()
    table.rows = []
  }
  // table stop loading
  table.isLoading = false
}

// onMounted时加载初始table第一页
onMounted(loadRows)
/* table end */

/* pagination */
const pagination = reactive({
  rowsPerPageOptions: [25, 50, 100, 200, 300, 500, 1000], // 每页条数选项
  rowsPerPage: 25, // 每页条数
  page: 1, // 当前页码
  count: 0 // 总共条数
})
// 复位当前页面选择
const resetPageSelection = () => {
  pagination.page = 1
}
// 复位pagination信息，网络请求失败、筛选失败时使用
const resetPagination = () => {
  // pagination.rowsPerPage = 50
  pagination.page = 1
  pagination.count = 0
}

// 复位所有条件，并重新读取页面
// const resetAllAndReload = () => {
//   resetFilters()
//   resetPageSelection()
//   loadRows()
//   clearRowSelection()
// }

/* pagination end */

/* row selection start */
const rowSelection = ref<MeetingReservation[]>([])
const clearRowSelection = () => {
  rowSelection.value = []
}
/* row selection end */

// 当前选中的会议
const selectedMeeting = ref<MeetingReservation | null>(null)
const meetingDetailsOpen = ref(false)
const loadingMeetingDetails = ref(false)

// 关闭会议详情
const closeMeetingDetails = () => {
  meetingDetailsOpen.value = false
  selectedMeeting.value = null
}

// 显示会议详情 (调用 API 获取最新数据)
const showMeetingDetails = async (meetingId: string) => {
  loadingMeetingDetails.value = true
  meetingDetailsOpen.value = true
  selectedMeeting.value = null
  try {
    const response = await api.service.txMeeting.getReservationDetail(meetingId, true)
    selectedMeeting.value = response.data
  } catch (error) {
    console.error('Error fetching meeting details:', error)
    Notify.create({
      message: tc('获取会议详情失败'),
      type: 'negative',
      icon: 'error',
      position: 'top'
    })
    closeMeetingDetails()
  } finally {
    loadingMeetingDetails.value = false
  }
}

// 强制释放会议资源 (调用取消接口)
const cancellingMeeting = ref(false)
const forceReleaseMeeting = async () => {
  if (!selectedMeeting.value || cancellingMeeting.value) return

  const meetingId = selectedMeeting.value.id
  cancellingMeeting.value = true
  const dismiss = Notify.create({
    message: tc('正在取消/释放会议...'),
    type: 'ongoing',
    position: 'center',
    timeout: 0
  })

  try {
    await api.service.txMeeting.cancelReservation(meetingId)
    dismiss()
    Notify.create({
      message: tc('会议已取消/释放'),
      type: 'positive',
      icon: 'check',
      position: 'top'
    })
    closeMeetingDetails()
    loadRows()
  } catch (error) {
    dismiss()
    console.error('Error cancelling meeting:', error)
    Notify.create({
      message: tc('取消/释放会议失败'),
      type: 'negative',
      icon: 'error',
      position: 'top'
    })
  } finally {
    cancellingMeeting.value = false
  }
}
</script>

<template>
  <q-scroll-area style="height: calc(100vh - 50px)">
    <div class="q-pa-md">
      <h5 class="q-mt-none q-mb-md">{{ tc('预定管理') }}</h5>

      <!-- 筛选区域 -->
      <div class="q-mb-lg">
        <div class="row q-col-gutter-md items-end">
          <!-- 输入框和选择框区域 - 自动换行 -->
          <div class="col-12 col-lg">
            <div class="row q-col-gutter-md">
              <!-- 日期范围 -->
              <div class="col-12 col-sm-4 col-md-6 col-lg">
                <q-input outlined v-model="filter.from" :label="tc('开始日期')" dense>
                  <template v-slot:append>
                    <q-icon name="event" class="cursor-pointer">
                      <q-popup-proxy cover transition-show="scale" transition-hide="scale">
                        <q-date v-model="filter.from" mask="YYYY/MM/DD">
                          <div class="row items-center justify-end">
                            <q-btn v-close-popup :label="tc('确定')" color="primary" flat />
                          </div>
                        </q-date>
                      </q-popup-proxy>
                    </q-icon>
                  </template>
                </q-input>
              </div>

              <div class="col-12 col-sm-4 col-md-6 col-lg">
                <q-input outlined v-model="filter.to" :label="tc('结束日期')" dense>
                  <template v-slot:append>
                    <q-icon name="event" class="cursor-pointer">
                      <q-popup-proxy cover transition-show="scale" transition-hide="scale">
                        <q-date v-model="filter.to" mask="YYYY/MM/DD">
                          <div class="row items-center justify-end">
                            <q-btn v-close-popup :label="tc('确定')" color="primary" flat />
                          </div>
                        </q-date>
                      </q-popup-proxy>
                    </q-icon>
                  </template>
                </q-input>
              </div>

              <div class="col-12 col-sm-4 col-md-6 col-lg">
                <q-select :label-color="filter.roomTypeSelection !== 'all' ? 'primary' : ''" outlined dense stack-label
                  :label="tc('筛选会议室类型')" v-model="filter.roomTypeSelection" :options="filter.roomTypeOptions" emit-value
                  map-options option-value="value" :option-label="i18n.global.locale === 'zh-CN' ? 'label' : 'labelEn'">
                  <template v-slot:option="scope">
                    <q-item v-bind="scope.itemProps">
                      <q-item-section>
                        <q-item-label>{{ scope.opt.label }}</q-item-label>
                      </q-item-section>
                    </q-item>
                  </template>
                </q-select>
              </div>

              <div class="col-12 col-sm-4 col-md-6 col-lg">
                <q-select :label-color="filter.statusSelection !== 'all' ? 'primary' : ''" outlined dense stack-label
                  :label="tc('筛选预定状态')" v-model="filter.statusSelection" :options="filter.statusOptions" emit-value
                  map-options option-value="value" :option-label="i18n.global.locale === 'zh-CN' ? 'label' : 'labelEn'">
                  <template v-slot:option="scope">
                    <q-item v-bind="scope.itemProps">
                      <q-item-section>
                        <q-item-label>{{ scope.opt.label }}</q-item-label>
                      </q-item-section>
                    </q-item>
                  </template>
                </q-select>
              </div>

              <div class="col-12 col-sm-4 col-md-6 col-lg">
                <q-input :label-color="filter.txMeetingCode ? 'primary' : ''" v-model.trim="filter.txMeetingCode"
                  outlined dense :label="tc('筛选腾讯会议号')"
                  @keyup.enter="resetPageSelection(); loadRows(); clearRowSelection()">
                  <template v-slot:append v-if="filter.txMeetingCode">
                    <q-icon name="close" @click="filter.txMeetingCode = ''" class="cursor-pointer" />
                  </template>
                </q-input>
              </div>
            </div>
          </div>

          <!-- 按钮区域 - 不换行 -->
          <div class="col-12 col-lg-auto">
            <div class="row full-width justify-start q-gutter-sm">
              <q-btn flat no-caps dense color="primary"
                @click="resetFilters(); resetPageSelection(); loadRows(); clearRowSelection()">
                {{ tc('重置') }}
              </q-btn>
              <q-btn unelevated no-caps color="primary" @click="resetPageSelection(); loadRows(); clearRowSelection()">
                {{ tc('搜索') }}
              </q-btn>
            </div>
          </div>
        </div>
      </div>

      <!-- 搜索条件改变提示 -->
      <q-banner v-if="isFiltersChanged" class="bg-blue-1 text-blue-9 q-mb-md">
        <template v-slot:avatar>
          <q-icon name="info" color="info" />
        </template>
        {{ tc('搜索条件已更新，请点击搜索按钮') }}
      </q-banner>

      <div v-if="!isFiltersChanged" class="row items-center justify-between">
        <div class="col-auto row items-center">
          <div class="col-auto text-grey">{{ tc('搜索结果总计') }}</div>
          <div class="col-auto ">{{ pagination.count }}</div>
        </div>
      </div>

      <!-- 桌面端表格视图 -->
      <q-table v-if="!isFiltersChanged && !$q.screen.lt.md" flat card-class="" table-class=""
        table-header-class="bg-grey-1 text-grey" :rows="table.rows" :columns="table.columns" :loading="table.isLoading"
        color="primary" :loading-label="tc('网络请求中')" :no-data-label="tc('无搜索结果')" hide-pagination
        :pagination="{ rowsPerPage: 0 }" row-key="id" v-model:selected="rowSelection">

        <template v-slot:body="props">
          <q-tr :props="props" @mouseenter="onMouseEnterRow(props.row?.id)" @mouseleave="onMouseLeaveRow">

            <q-td key="creation_time" :props="props">
              <div>
                {{ formatDate(props.row?.creation_time).split(' ')[0] }}
              </div>
              <div>
                {{ formatDate(props.row?.creation_time).split(' ')[1] }}
              </div>
            </q-td>

            <q-td key="subject" :props="props">
              {{ props.row?.subject }}
            </q-td>

            <q-td key="tx_meeting_code" :props="props">
              {{ props.row?.tx_meeting_code }}
            </q-td>

            <q-td key="start_time" :props="props">
              <div>
                {{ formatDate(props.row?.start_time).split(' ')[0] }}
              </div>
              <div>
                {{ formatDate(props.row?.start_time).split(' ')[1] }}
              </div>
            </q-td>

            <q-td key="end_time" :props="props">
              <div>
                {{ formatDate(props.row?.end_time).split(' ')[0] }}
              </div>
              <div>
                {{ formatDate(props.row?.end_time).split(' ')[1] }}
              </div>
            </q-td>

            <q-td key="room_type" :props="props">
              {{ props.row?.room_type }} {{ tc('方') }}
            </q-td>

            <q-td key="creator" :props="props">
              <div class="column">
                <div class="col-auto">
                  {{ props.row?.tx_user_nick_name }}
                </div>
                <div class="col-auto">
                  {{ props.row?.tx_meeting_userid }}
                </div>
              </div>
            </q-td>

            <q-td key="user" :props="props">
              <div class="column">
                <div class="col-auto">
                  {{ props.row?.user?.full_name }}
                </div>
                <div class="col-auto">
                  {{ props.row?.user?.username }}
                </div>
              </div>
            </q-td>

            <q-td key="reserve_status" :props="props">
              <q-chip :color="props.row.status === 'reserved' ? 'positive' : 'grey'" text-color="white" dense square>
                {{ props.row.status === 'reserved' ? tc('已预定') : tc('已取消') }}
              </q-chip>
            </q-td>

            <q-td key="room_status" :props="props" class="non-selectable">
              <q-chip
                :color="props.row.room_reserve_status === 'reserved' ? 'positive' : props.row.room_reserve_status === 'wait' ? 'warning' : 'negative'"
                text-color="white" dense square>
                {{
                  props.row.room_reserve_status === 'wait' ? tc('待预留') : props.row.room_reserve_status === 'unreserved' ?
                    tc('预留失败') : props.row.room_reserve_status === 'reserved' ? tc('已预留') : props.row.room_reserve_status
                      ===
                      'unreleased' ? tc('释放失败') : props.row.room_reserve_status === 'released' ? tc('已释放') :
                      props.row.room_reserve_status
                }}
              </q-chip>
            </q-td>

            <q-td key="operation" :props="props" class="non-selectable">
              <div class="row justify-start">
                <q-btn flat dense round color="primary" icon="info" @click="showMeetingDetails(props.row.id)">
                  <q-tooltip>{{ tc('查看详情') }}</q-tooltip>
                </q-btn>
                <q-btn v-if="props.row.status === 'reserved'" flat dense round icon="cancel" color="negative"
                  @click="selectedMeeting = props.row; forceReleaseMeeting()">
                  <q-tooltip>{{ tc('取消/释放会议') }}</q-tooltip>
                </q-btn>
              </div>
            </q-td>

          </q-tr>
        </template>

        <template v-slot:bottom>
          <div class="row full-width items-center justify-end">
            <div class="col row items-center justify-end text-grey">
              <q-select color="grey" v-model="pagination.rowsPerPage" :options="pagination.rowsPerPageOptions" dense
                options-dense borderless @update:model-value="resetPageSelection(); loadRows(); clearRowSelection()">
              </q-select>
              {{ tc('项/页') }}
            </div>

            <q-pagination v-model="pagination.page" :max="Math.ceil(pagination.count / pagination.rowsPerPage)"
              :max-pages="9" direction-links outline :ripple="false"
              @update:model-value="loadRows(); clearRowSelection()" />
          </div>
        </template>
      </q-table>

      <!-- 移动端卡片视图 -->
      <div v-if="!isFiltersChanged && $q.screen.lt.md">
        <!-- 加载状态 -->
        <q-inner-loading :showing="table.isLoading">
          <q-spinner-gears size="50px" color="primary" />
        </q-inner-loading>

        <!-- 无数据提示 -->
        <div v-if="!table.isLoading && table.rows.length === 0" class="text-center q-pa-lg text-grey">
          {{ tc('无搜索结果') }}
        </div>

        <!-- 会议预定卡片列表 -->
        <div v-if="!table.isLoading && table.rows.length > 0" class="q-gutter-md">
          <q-card v-for="row in table.rows" :key="row.id" class="q-mb-md" flat bordered>
            <q-card-section class="q-pa-sm">
              <!-- 会议主题 -->
              <div class="q-mb-sm">
                <div class="text-h6 text-weight-medium q-mb-xs" style="line-height: 1.2; word-break: break-all;">
                  {{ row.subject }}
                </div>
                <!-- 预定状态 -->
                <q-chip :color="row.status === 'reserved' ? 'positive' : 'grey'" text-color="white" dense square
                  size="sm">
                  {{ row.status === 'reserved' ? tc('已预定') : tc('已取消') }}
                </q-chip>
              </div>

              <!-- 会议号 -->
              <div class="q-mb-xs">
                <div class="text-grey-7 text-caption q-mb-xs">{{ tc('会议号') }}</div>
                <div class="text-body2 text-weight-medium">{{ row.tx_meeting_code }}</div>
              </div>

              <!-- 预定时间 -->
              <div class="q-mb-xs">
                <div class="text-grey-7 text-caption q-mb-xs">{{ tc('会议时间') }}</div>
                <div class="text-body2">
                  <div>{{ formatDate(row.start_time) }}</div>
                  <div class="text-grey">{{ tc('至') }} {{ formatDate(row.end_time) }}</div>
                </div>
              </div>

              <!-- 创建时间 -->
              <div class="q-mb-xs">
                <div class="text-grey-7 text-caption q-mb-xs">{{ tc('创建时间') }}</div>
                <div class="text-body2">{{ formatDate(row.creation_time) }}</div>
              </div>

              <!-- 会议室类型 -->
              <div class="q-mb-xs">
                <div class="text-grey-7 text-caption q-mb-xs">{{ tc('会议室') }}</div>
                <div class="text-body2">{{ row.room_type }}{{ tc('方') }}</div>
              </div>

              <!-- 创建人 -->
              <div class="q-mb-xs">
                <div class="text-grey-7 text-caption q-mb-xs">{{ tc('创建人') }}</div>
                <div class="text-body2">
                  <div>{{ row.tx_user_nick_name }}</div>
                  <div class="text-grey text-caption">{{ row.tx_meeting_userid }}</div>
                </div>
              </div>

              <!-- 预定人 -->
              <div class="q-mb-xs">
                <div class="text-grey-7 text-caption q-mb-xs">{{ tc('预定人') }}</div>
                <div class="text-body2">
                  <div>{{ row.user?.full_name }}</div>
                  <div class="text-grey text-caption">{{ row.user?.username }}</div>
                </div>
              </div>

              <!-- 会议室状态 -->
              <div class="q-mb-sm">
                <div class="text-grey-7 text-caption q-mb-xs">{{ tc('会议室状态') }}</div>
                <q-chip
                  :color="row.room_reserve_status === 'reserved' ? 'positive' : row.room_reserve_status === 'wait' ? 'warning' : 'negative'"
                  text-color="white" dense square size="sm">
                  {{
                    row.room_reserve_status === 'wait' ? tc('待预留') : row.room_reserve_status === 'unreserved' ?
                      tc('预留失败') : row.room_reserve_status === 'reserved' ? tc('已预留') : row.room_reserve_status ===
                        'unreleased' ?
                        tc('释放失败') : row.room_reserve_status === 'released' ? tc('已释放') : row.room_reserve_status
                  }}
                </q-chip>
              </div>

              <!-- 操作按钮 -->
              <div class="row q-gutter-xs">
                <q-btn flat dense color="primary" icon="info" :label="tc('详情')" size="sm" class="col"
                  @click="showMeetingDetails(row.id)" />
                <q-btn v-if="row.status === 'reserved'" flat dense icon="cancel" color="negative" :label="tc('取消')"
                  size="sm" class="col" @click="selectedMeeting = row; forceReleaseMeeting()" />
              </div>
            </q-card-section>
          </q-card>
        </div>

        <!-- 移动端分页 -->
        <div v-if="!table.isLoading && table.rows.length > 0" class="q-mt-lg">
          <div class="row items-center justify-between q-mb-md">
            <div class="text-grey text-body2">
              {{ tc('搜索结果总计') }}: {{ pagination.count }}
            </div>
            <q-select color="grey" v-model="pagination.rowsPerPage" :options="pagination.rowsPerPageOptions" dense
              options-dense outlined @update:model-value="resetPageSelection(); loadRows(); clearRowSelection()"
              style="min-width: 100px;">
              <template v-slot:after>
                <span class="text-grey q-ml-sm">{{ tc('项/页') }}</span>
              </template>
            </q-select>
          </div>

          <div class="row justify-center">
            <q-pagination v-model="pagination.page" :max="Math.ceil(pagination.count / pagination.rowsPerPage)"
              :max-pages="5" direction-links outline :ripple="false" size="sm"
              @update:model-value="loadRows(); clearRowSelection()" />
          </div>
        </div>
      </div>

      <!-- 会议详情 Dialog -->
      <q-dialog v-model="meetingDetailsOpen" persistent @hide="closeMeetingDetails" :full-width="$q.screen.lt.md"
        :full-height="$q.screen.lt.md">
        <q-card
          :style="$q.screen.lt.md ? 'width: 100vw; height: 100vh; max-width: none; max-height: none;' : 'min-width: 450px; max-width: 600px; max-height: 80vh;'"
          class="column">
          <q-card-section class="row items-center" :class="$q.screen.lt.md ? 'q-pa-md' : ''">
            <div class="text-h6">{{ tc('会议详情') }}</div>
            <q-space />
            <q-btn icon="close" flat round dense v-close-popup />
          </q-card-section>

          <q-separator />

          <q-card-section v-if="loadingMeetingDetails" class="col">
            <q-inner-loading showing>
              <q-spinner-gears size="50px" color="primary" />
            </q-inner-loading>
            <div :style="$q.screen.lt.md ? 'height: 200px;' : 'height: 300px;'"></div>
          </q-card-section>

          <q-card-section v-else-if="selectedMeeting" class="col" :class="$q.screen.lt.md ? 'q-pa-md' : ''"
            style="overflow-y: auto;">
            <div class="q-mb-sm">
              <span class="text-subtitle2 text-grey-7">{{ tc('会议主题') }}</span>
              <div class="q-mt-xs text-body2">{{ selectedMeeting.subject }}</div>
            </div>

            <div class="q-mb-sm">
              <span class="text-subtitle2 text-grey-7">{{ tc('会议号') }}</span>
              <div class="q-mt-xs text-body2">{{ selectedMeeting.tx_meeting_code }}</div>
            </div>

            <div class="q-mb-sm">
              <span class="text-subtitle2 text-grey-7">{{ tc('预定时间') }}</span>
              <div class="q-mt-xs text-body2">
                {{ formatDate(selectedMeeting.start_time) }} - {{ formatDate(selectedMeeting.end_time) }}
              </div>
            </div>

            <div class="q-mb-sm">
              <span class="text-subtitle2 text-grey-7">{{ tc('会议室预留时间') }}</span>
              <div class="q-mt-xs text-body2">
                {{ formatDate(selectedMeeting.room_reserve_start) }} - {{ formatDate(selectedMeeting.room_reserve_end)
                }}
              </div>
            </div>

            <div class="q-mb-sm">
              <span class="text-subtitle2 text-grey-7">{{ tc('会议室类型') }}</span>
              <div class="q-mt-xs text-body2">{{ selectedMeeting.room_type }}方</div>
            </div>

            <div class="q-mb-sm">
              <span class="text-subtitle2 text-grey-7">{{ tc('预定人') }}</span>
              <div class="q-mt-xs text-body2">
                {{ selectedMeeting.user?.full_name }} ({{ selectedMeeting.user?.username }})
              </div>
            </div>

            <div class="q-mb-sm">
              <span class="text-subtitle2 text-grey-7">{{ tc('预定状态') }}</span>
              <div class="q-mt-xs">
                <q-chip :color="selectedMeeting.status === 'reserved' ? 'positive' : 'grey'" text-color="white" dense
                  square>
                  {{ selectedMeeting.status === 'reserved' ? tc('已预定') : tc('已取消') }}
                </q-chip>
              </div>
            </div>

            <div class="q-mb-sm">
              <span class="text-subtitle2 text-grey-7">{{ tc('会议室预留状态') }}</span>
              <div class="q-mt-xs">
                <q-chip
                  :color="selectedMeeting.room_reserve_status === 'reserved' ? 'positive' : selectedMeeting.room_reserve_status === 'wait' ? 'warning' : 'negative'"
                  text-color="white" dense square>
                  {{
                    selectedMeeting.room_reserve_status === 'wait' ? tc('待预留') : selectedMeeting.room_reserve_status ===
                      'unreserved' ? tc('预留失败') : selectedMeeting.room_reserve_status === 'reserved' ? tc('已预留') :
                      selectedMeeting.room_reserve_status === 'unreleased' ? tc('释放失败') :
                        selectedMeeting.room_reserve_status
                          ===
                          'released' ? tc('已释放') : selectedMeeting.room_reserve_status
                  }}
                </q-chip>
              </div>
            </div>

            <div class="q-mb-sm">
              <span class="text-subtitle2 text-grey-7">{{ tc('预留信息') }}</span>
              <div v-if="selectedMeeting.room_reserve_desc" class="q-mt-xs text-body2">
                {{ selectedMeeting.room_reserve_desc }}
              </div>
            </div>

            <div class="q-mb-sm">
              <span class="text-subtitle2 text-grey-7">{{ tc('腾讯会议加入链接') }}</span>
              <div class="q-mt-xs">
                <a :href="selectedMeeting.tx_join_url" target="_blank" class="text-primary text-body2"
                  style="word-break: break-all;">
                  {{ selectedMeeting.tx_join_url }}
                </a>
              </div>
            </div>

            <div class="q-mb-sm">
              <span class="text-subtitle2 text-grey-7">{{ tc('会前提醒') }}</span>
              <div class="q-mt-xs text-body2">
                {{ selectedMeeting.advance_notice_seconds / 60 }} {{ tc('分钟') }}
              </div>
            </div>

            <div v-if="selectedMeeting.email_notice">
              <q-separator class="q-my-md" />
              <div class="text-subtitle1 q-mb-md">{{ tc('邮件通知详情') }}</div>

              <div class="q-mb-sm">
                <span class="text-subtitle2 text-grey-7">{{ tc('状态') }}</span>
                <div class="q-mt-xs text-body2">{{ selectedMeeting.email_notice.status }}</div>
              </div>

              <div class="q-mb-sm">
                <span class="text-subtitle2 text-grey-7">{{ tc('接收人') }}</span>
                <div class="q-mt-xs text-body2" style="word-break: break-all;">{{ selectedMeeting.email_notice.receiver
                  }}
                </div>
              </div>

              <div class="q-mb-sm">
                <span class="text-subtitle2 text-grey-7">{{ tc('发送时间') }}</span>
                <div class="q-mt-xs text-body2">{{ formatDate(selectedMeeting.email_notice.send_time) }}</div>
              </div>

              <div v-if="selectedMeeting.email_notice.status_desc" class="text-caption text-negative q-mt-xs">
                {{ selectedMeeting.email_notice.status_desc }}
              </div>
            </div>

          </q-card-section>

          <q-separator />

          <q-card-actions :align="$q.screen.lt.md ? 'around' : 'between'" :class="$q.screen.lt.md ? 'q-pa-md' : ''">
            <q-btn v-if="selectedMeeting?.status === 'reserved'" :label="tc('取消/释放会议')" color="negative"
              @click="forceReleaseMeeting" :loading="cancellingMeeting" :disable="cancellingMeeting"
              :class="$q.screen.lt.md ? 'full-width q-mb-sm' : ''"></q-btn>
            <q-btn :label="tc('关闭')" color="grey" unelevated v-close-popup
              :class="$q.screen.lt.md ? 'full-width' : ''"></q-btn>
          </q-card-actions>
        </q-card>
      </q-dialog>

    </div>
  </q-scroll-area>
</template>

<style lang="scss" scoped></style>
